package com.zhoug.zmui;

import android.content.Context;
import android.content.res.TypedArray;
import android.util.AttributeSet;
import android.util.Log;
import android.view.View;
import android.view.ViewGroup;
import android.widget.LinearLayout;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

import androidx.annotation.Nullable;

/**
 * 根据宽高自动显示和隐藏子组件
 * @Author: zhoug
 * @Date: 2024-11-13
 * @Description:
 */
public class ZMUIAutoHideLinearLayout extends LinearLayout {
    private static final String TAG = ">>>AutoHideLinearLayout";

    public ZMUIAutoHideLinearLayout(Context context) {
        super(context);
    }

    public ZMUIAutoHideLinearLayout(Context context, @Nullable AttributeSet attrs) {
        super(context, attrs);
    }

    public ZMUIAutoHideLinearLayout(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
    }

    public ZMUIAutoHideLinearLayout(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
        super(context, attrs, defStyleAttr, defStyleRes);

    }
    //支持自动改变现实状态的views
    List<View> autoChildren = new ArrayList<>();
    List<View> changeViews = new ArrayList<>();


    @Override
    protected void onLayout(boolean changed, int l, int t, int r, int b) {
        super.onLayout(changed, l, t, r, b);
        Log.d(TAG, "onLayout:");
        autoChildren.clear();
        changeViews.clear();
        int childCount = getChildCount();
        if (childCount > 0) {
            boolean isHorizontal=getOrientation()==HORIZONTAL;
            int contentLength;
            if(isHorizontal){
                contentLength = getMeasuredWidth() - getPaddingStart() - getPaddingEnd();
            }else{
                contentLength = getMeasuredHeight() - getPaddingTop() - getPaddingBottom();
            }
            //计算child总共占用的空间
            int lengUsed = 0;
            for (int i = 0; i < childCount; i++) {
                View child = getChildAt(i);
                LayoutParams layoutParams = (LayoutParams) child.getLayoutParams();
                if (child.getVisibility() == VISIBLE) {
                    if(isHorizontal){
                        lengUsed += child.getMeasuredWidth();
                        lengUsed += layoutParams.getMarginStart() + layoutParams.getMarginEnd();
                    }else{
                        lengUsed += child.getMeasuredHeight();
                        lengUsed += layoutParams.topMargin + layoutParams.bottomMargin;
                    }

                }
                if(layoutParams.autoVisibility){
                    autoChildren.add(child);
                }
            }

            Log.d(TAG, "onLayout:contentLength=" + contentLength + ",lengUsed=" + lengUsed);
            if (lengUsed > contentLength) {
                //需要隐藏
                //优先级由低到高排序
                sort(autoChildren);
                for (int i = 0; i < autoChildren.size(); i++) {
                    View child = autoChildren.get(i);
                    if(child.getVisibility()==VISIBLE){
                        LayoutParams layoutParams = (LayoutParams) child.getLayoutParams();
                        if (layoutParams.autoVisibility) {
                            if(isHorizontal){
                                lengUsed -= child.getMeasuredWidth();
                                lengUsed -= layoutParams.getMarginStart() + layoutParams.getMarginEnd();
                            }else{
                                lengUsed -= child.getMeasuredHeight();
                                lengUsed -= layoutParams.topMargin + layoutParams.bottomMargin;
                            }
                            changeViews.add(child);
                            if (lengUsed <= contentLength) {
                                break;
                            }
                        }
                    }

                }
                Log.d(TAG, "onLayout:contentLength=" + contentLength + ",lengUsed=" + lengUsed);
                if (!changeViews.isEmpty()) {
                    post(() -> {
                        for (int i = 0; i < changeViews.size(); i++) {
                            changeViews.get(i).setVisibility(GONE);
                        }
                        changeViews.clear();
                    });
                }
            }else if(lengUsed<contentLength){
                //可能需要显示
                //优先级由高到低排序
                sortDesc(autoChildren);
                for (int i = 0; i < autoChildren.size(); i++) {
                    View child = autoChildren.get(i);
                    if(child.getVisibility()==GONE){
                        LayoutParams layoutParams = (LayoutParams) child.getLayoutParams();
                        if (layoutParams.autoVisibility) {
                            if(isHorizontal){
                                lengUsed += child.getMeasuredWidth();
                                lengUsed += layoutParams.getMarginStart() + layoutParams.getMarginEnd();
                            }else{
                                lengUsed += child.getMeasuredHeight();
                                lengUsed += layoutParams.topMargin + layoutParams.bottomMargin;
                            }
                            if (lengUsed > contentLength) {
                                break;
                            }else{
                                changeViews.add(child);
                            }
                        }
                    }

                }
                Log.d(TAG, "onLayout:contentLength=" + contentLength + ",lengUsed=" + lengUsed);
                if (!changeViews.isEmpty()) {
                    post(() -> {
                        for (int i = 0; i < changeViews.size(); i++) {
                            changeViews.get(i).setVisibility(VISIBLE);
                        }
                        changeViews.clear();
                    });
                }

            }
            autoChildren.clear();

        }
    }

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        super.onMeasure(widthMeasureSpec, heightMeasureSpec);
        Log.d(TAG, "onMeasure:");
    }

    private void sort(List<View> views) {
        if (views == null || views.isEmpty()) return;
        Collections.sort(views, (view1, view2) -> {
            int viewPriority1 = ((LayoutParams) view1.getLayoutParams()).priority;
            int viewPriority2 = ((LayoutParams) view2.getLayoutParams()).priority;
            return viewPriority1 - viewPriority2;
        });
    }

    private void sortDesc(List<View> views) {
        if (views == null || views.isEmpty()) return;
        Collections.sort(views, (view1, view2) -> {
            int viewPriority1 = ((LayoutParams) view1.getLayoutParams()).priority;
            int viewPriority2 = ((LayoutParams) view2.getLayoutParams()).priority;
            return viewPriority2 - viewPriority1;
        });
    }

    @Override
    protected LinearLayout.LayoutParams generateDefaultLayoutParams() {
        if (getOrientation() == HORIZONTAL) {
            return new LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.WRAP_CONTENT);
        } else if (getOrientation() == VERTICAL) {
            return new LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.MATCH_PARENT);
        }
        return null;
    }

    @Override
    protected LinearLayout.LayoutParams generateLayoutParams(ViewGroup.LayoutParams lp) {
//         super.generateLayoutParams(lp);
        if (lp instanceof LayoutParams) {
            return new LayoutParams((LayoutParams) lp);
        } else if (lp instanceof MarginLayoutParams) {
            return new LayoutParams((MarginLayoutParams) lp);
        }
        return new LayoutParams(lp);
    }

    @Override
    public LinearLayout.LayoutParams generateLayoutParams(AttributeSet attrs) {
        return new LayoutParams(getContext(), attrs);
    }


    @Override
    protected boolean checkLayoutParams(ViewGroup.LayoutParams p) {
        return p instanceof LayoutParams;
    }

    public static class LayoutParams extends LinearLayout.LayoutParams {
        /**
         * 优先级,数字越大优先级越高,优先级低的先被隐藏
         */
        public int priority;
        /**
         * 当内容显示不下时是否可以隐藏,内容充足时是否可以显示
         */
        public boolean autoVisibility = true;

        /**
         * {@inheritDoc}
         *
         * @param c
         * @param attrs
         */
        public LayoutParams(Context c, AttributeSet attrs) {
            super(c, attrs);
            TypedArray a = c.obtainStyledAttributes(attrs, R.styleable.ZMUIAutoHideLinearLayout_Layout);
            priority = a.getInt(R.styleable.ZMUIAutoHideLinearLayout_Layout_zmui_layout_priority, 0);
            autoVisibility = a.getBoolean(R.styleable.ZMUIAutoHideLinearLayout_Layout_zmui_layout_autoVisibility, true);
            a.recycle();
        }

        /**
         * {@inheritDoc}
         *
         * @param width
         * @param height
         */
        public LayoutParams(int width, int height) {
            super(width, height);
        }

        /**
         * Creates a new set of layout parameters with the specified width, height
         * and weight.
         *
         * @param width  the width, either {@link #MATCH_PARENT},
         *               {@link #WRAP_CONTENT} or a fixed size in pixels
         * @param height the height, either {@link #MATCH_PARENT},
         *               {@link #WRAP_CONTENT} or a fixed size in pixels
         * @param weight the weight
         */
        public LayoutParams(int width, int height, float weight) {
            super(width, height, weight);
        }

        /**
         * {@inheritDoc}
         *
         * @param p
         */
        public LayoutParams(ViewGroup.LayoutParams p) {
            super(p);
        }

        /**
         * {@inheritDoc}
         *
         * @param source
         */
        public LayoutParams(MarginLayoutParams source) {
            super(source);
        }

        /**
         * Copy constructor. Clones the width, height, margin values, weight,
         * and gravity of the source.
         *
         * @param source The layout params to copy from.
         */
        public LayoutParams(LinearLayout.LayoutParams source) {
            super(source);
        }





    }


}
